﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using io = System.IO;
using wf = System.Windows.Forms;
using dw = System.Drawing;

namespace editor.app
{
    /// <summary>
    /// MapView.xaml 的交互逻辑
    /// </summary>
    public partial class MapView : UserControl
    {
        public class Obj
        {
            MapView _view = null;
            public string _objKey = "";
            public comm.objst.DMap.Data.Obj _obj = null;
            public comm.objst.DMap.Data.SObj _sobj = null;
            public Dictionary<string, Border> _brDotDic = new Dictionary<string, Border>();
            Grid _gridRoot = null;
            public Ellipse _ellDot = null;

            int _pathSize = 0;
            static Grid _lasSelGrid = null;

            public Obj(MapView mapView, string objKey)
            {
                _view = mapView;
                _objKey = objKey;
                _obj = _view._map.ObjDic[_objKey];
                _pathSize = _view.PathSize;

                if (_obj is comm.objst.DMap.Data.SObj)
                {
                    _sobj = (comm.objst.DMap.Data.SObj)_obj;
                }

                _gridRoot = new Grid { Opacity = _sobj == null ? .5 : 1 };
                _gridRoot.SetLeftTop(_obj.LocX * _pathSize, _obj.LocY * _pathSize);
                _gridRoot.MouseEnter += new MouseEventHandler(_gridRoot_MouseEnter);
                _view.cvObj.Children.Add(_gridRoot);

                Reload();
            }

            void _gridRoot_MouseEnter(object sender, MouseEventArgs e)
            {
                try
                {
                    _lasSelGrid.Background = null;
                }
                catch (Exception)
                {
                }
                _lasSelGrid = _gridRoot;
                _lasSelGrid.Background = new SolidColorBrush(Color2.Orange(10));
                _view.ReceiveCmd("objEnter", this);
            }

            public void Reload()
            {
                _brDotDic.Clear();
                _gridRoot.Children.Clear();

                #region IsExternal
                if (_obj.IsExternal)
                {
                    var mr = 10;
                    _gridRoot.Children.Add(new Border
                    {
                        Width = _pathSize + mr,
                        Height = _pathSize + mr,
                        Margin = new Thickness(-mr / 2, -mr / 2, 0, 0),
                        CornerRadius = new CornerRadius(_pathSize + mr),
                        VerticalAlignment = VerticalAlignment.Top,
                        HorizontalAlignment = HorizontalAlignment.Left,
                        Background = new SolidColorBrush(Color2.Yellow(30)),
                        BorderBrush = new SolidColorBrush(Color2.Yellow(80)),
                        BorderThickness = new Thickness(1)
                    });
                }
                #endregion

                #region dot
                _ellDot = new Ellipse
                {
                    Width = _pathSize,
                    Height = _pathSize,
                    Fill = new SolidColorBrush(Color2.White(70)),
                    VerticalAlignment = VerticalAlignment.Top,
                    HorizontalAlignment = HorizontalAlignment.Left
                };
                _gridRoot.Children.Add(_ellDot);
                #endregion

                #region name
                var tbName = new TextBlock
                {
                    Text = _obj.Name,
                    FontSize = 12,
                    FontFamily = new FontFamily("SimSun"),
                    MaxWidth = 90,
                    Height = 16,
                    Margin = new Thickness(_pathSize + 6, 0, 0, 0),
                    VerticalAlignment = VerticalAlignment.Top,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    Foreground = new SolidColorBrush(Color2.White(50)),
                };
                TextOptions.SetTextFormattingMode(tbName, TextFormattingMode.Display);
                _gridRoot.Children.Add(tbName);
                #endregion

                if (_sobj != null && _sobj.EVDic.Count > 0)
                {
                    var sp = new StackPanel();
                    foreach (var evKey in _sobj.EVDic.Keys)
                    {
                        var item = _sobj.EVDic[evKey];
                        var grid = new Grid { Height = 18 };

                        #region tbKey
                        var tb = new TextBlock
                        {
                            Width = 80,
                            FontSize = 12,
                            FontFamily = new FontFamily("SimSun"),
                            Text = item.Value.ToString(),
                            Foreground = new SolidColorBrush(Color2.Yellow()),
                            Margin = new Thickness(20, 0, 0, 0),
                            VerticalAlignment = VerticalAlignment.Center
                        };
                        TextOptions.SetTextFormattingMode(tb, TextFormattingMode.Display);
                        grid.Children.Add(tb);
                        #endregion

                        #region br dot
                        var brDot = new Border
                        {
                            Tag = evKey,
                            Width = 16,
                            Height = 16,
                            CornerRadius = new CornerRadius(20),
                            Background = new SolidColorBrush(Color2.Black(30)),
                            BorderBrush = new SolidColorBrush(Color2.White(80)),
                            BorderThickness = new Thickness(1),
                            HorizontalAlignment = HorizontalAlignment.Left,
                            VerticalAlignment = VerticalAlignment.Center
                        };
                        brDot.MouseEnter += new MouseEventHandler((o, e) =>
                        {
                            brDot.Background = new SolidColorBrush(Color2.Black(50));
                        });
                        brDot.MouseLeave += new MouseEventHandler((o, e) =>
                        {
                            brDot.Background = new SolidColorBrush(Color2.Black(30));
                        });
                        brDot.MouseLeftButtonDown += new MouseButtonEventHandler((o, e) =>
                        {
                            e.Handled = true;
                            _view.ReceiveCmd("evClick", this, brDot.Tag.ToString(), brDot);
                        });

                        if (item.Value is comm.lib.MapEvent.MoveToSpace ||
                            item.Value is comm.lib.MapEvent.MoveToLocLabel)
                        {
                            _brDotDic.Add(evKey, brDot);
                            grid.Children.Add(brDot);
                        }
                        #endregion

                        sp.Children.Add(grid);
                    }
                    _gridRoot.Children.Add(new Border
                    {
                        Child = sp,
                        Padding = new Thickness(4),
                        BorderThickness = new Thickness(1),
                        BorderBrush = new SolidColorBrush(Color2.White(20)),
                        Background = new SolidColorBrush(Color2.White(10)),
                        HorizontalAlignment = HorizontalAlignment.Left,
                        VerticalAlignment = VerticalAlignment.Top,
                        Margin = new Thickness(_pathSize / 2, _pathSize / 2, 0, 0)
                    });
                }
            }
        }

        public string _spaceId = "";
        comm.objst.DMap.Data _map = null;
        public Action<string, MapView, object[]> CmdCallback = null;
        public Dictionary<string, Obj> _objDic = new Dictionary<string, Obj>();
        List<int[]> _pathList = null;

        public const int PATH_SIZE = 10;

        int _pathSize = PATH_SIZE;
        public int PathSize
        {
            get
            {
                return _pathSize;
            }
            set
            {
                value = Math.Max(2, value);
                _pathSize = value;
                Reload();
            }
        }

        public MapView()
        {
            InitializeComponent();

            gridRoot.MouseMove += new MouseEventHandler(gridRoot_MouseMove);
        }

        void gridRoot_MouseMove(object sender, MouseEventArgs e)
        {
            var pt = e.GetPosition(gridRoot);
            ReceiveCmd("mapMove",
                (int)Math.Floor(pt.X / PathSize),
                (int)Math.Floor(pt.Y / PathSize));
        }

        public void Load(string spaceId, comm.objst.DMap.Data map, List<int[]> pathList = null)
        {
            _spaceId = spaceId;
            _map = map;
            _pathList = pathList;
            Reload();
        }
        public void Reload()
        {
            int w = _map.Width * PathSize,
                h = _map.Height * PathSize;
            gridRoot.Width = w;
            gridRoot.Height = h;

            tbTips.Text = _spaceId + " " + _map.Width + "," + _map.Height;

            cvGrid.Children.Clear();
            cvObj.Children.Clear();
            cvPath.Children.Clear();
            cvMask.Children.Clear();

            _objDic.Clear();

            #region background
            var sc = PathSize / (double)_map.PathSize;
            foreach (var item in _map.BGImageBlockList)
            {
                if (item.ImageBytes != null)
                {
                    var bitmap = new BitmapImage();
                    bitmap.FromBytes(item.ImageBytes);
                    var blockImage = new Image
                    {
                        Source = bitmap,
                        Width = bitmap.PixelWidth * sc,
                        Height = bitmap.PixelHeight * sc
                    };
                    blockImage.SetLeftTop(item.X * sc, item.Y * sc);
                    cvGrid.Children.Add(blockImage);
                }
            }
            #endregion

            #region grid
            for (int x = 1; x < _map.Width; x++)
            {
                var rect = new Rectangle { Width = 1, Height = h, Fill = new SolidColorBrush(Color2.White(10)) };
                rect.SetLeft(x * PathSize);
                cvGrid.Children.Add(rect);
            }
            for (int y = 1; y < _map.Height; y++)
            {
                var rect = new Rectangle { Width = w, Height = 1, Fill = new SolidColorBrush(Color2.White(10)) };
                rect.SetTop(y * PathSize);
                cvGrid.Children.Add(rect);
            }
            #endregion

            if (_pathList != null)
            {
                var path = StarWindow.Block.MakePath(_pathList);
                path.Width = w;
                path.Height = h;
                path.Stretch = Stretch.Fill;
                path.Stroke = new SolidColorBrush(Color2.Orange(50));
                path.StrokeThickness = 2;
                cvGrid.Children.Add(path);
            }

            #region path
            var image = new Image { Width = w, Height = h };
            var bitmapImage = new BitmapImage();
            using (var bitmap = new dw.Bitmap(w, h))
            {
                var g = dw.Graphics.FromImage(bitmap);
                g.SmoothingMode = dw.Drawing2D.SmoothingMode.AntiAlias;
                for (int x = 0; x < _map.Width; x++)
                {
                    for (int y = 0; y < _map.Height; y++)
                    {
                        if (_map.Paths[x, y] == comm.objst.PathType.FORBID)
                        {
                            g.DrawRectangle(new dw.Pen(dw.Color.Yellow, 2),
                                new dw.Rectangle(x * PathSize, y * PathSize, PathSize, PathSize));
                        }
                    }
                }
                g.Dispose();
                using (var ms = new io.MemoryStream())
                {
                    bitmap.Save(ms, dw.Imaging.ImageFormat.Png);
                    bitmapImage.FromBytes(ms.ToArray());
                }
            }
            image.Source = bitmapImage;
            cvPath.Children.Add(image);
            #endregion

            foreach (var key in _map.ObjDic.Keys)
            {
                _objDic.Add(key, new Obj(this, key));
            }
        }
        public void ReceiveCmd(string cmd, params object[] args)
        {
            if (CmdCallback != null)
            {
                CmdCallback(cmd, this, args);
            }
        }
    }
}
